package gui

import ewu._
import java.awt.event.KeyEvent
import java.awt.event.KeyListener
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.FileWriter
import java.io.IOException
import javax.swing.filechooser.FileNameExtensionFilter
import parser._
import scala.swing.Dialog
import scala.swing.Dialog._
import scala.swing.EditorPane
import scala.swing.FileChooser
import lang.LOC
import java.util._

/**
 * Diese Klasse stellt die Verwaltung der geoeffneten
 * Dateien dar. Sie enthaelt Funktionen und Attribute
 * zum Speichern und Anzeigen von geoeffneten Tabs bzw.
 * Dateien.
 */

case class ScaProject(var name: String, var maindatei: File,tabpane: MyTabbedPane,
                      textpane: ScrollTextAreaPane = new ScrollTextAreaPane(true), 
                      var testproc: String = null, var testfile: File = null) {  
  
  var t1:String = ""
  var t2:String = ""
  var t3:String = ""
  var t4:String = ""
  
  var t1file:String = ""
  var t2file:String = ""
  var t3file:String = ""
  var t4file:String = ""
  
  //Bereits vorhandene Ausgabedateien laden
  loadOutput()
  
  //true, wenn bereits eine Datei zum Projekt vorhanden ist
  var saved = false;
  if(maindatei != null)
    saved = true;
  
  //true, wenn sich der Inhalt(text) der Datei geaendert wurde/hat
  var edited = false;
  
  //true, wenn bereits geparst
  var parsed = false;
  
  //KeyListener zum Textfeld hinzufuegen, um Aenderungen abfangen zu koennen
  textpane.textarea.peer.addKeyListener(new KeyListener(){
      def keyTyped(e:KeyEvent) {}

      def keyPressed(e:KeyEvent) {
        ScaProject.this.edited = true
        ScaProject.this.parsed = false
        tabpane.peer.setTitleAt(getTabIndex(), "*" + name)
      }

      def keyReleased(e:KeyEvent) {}
    })
  
  
  
  def getTextPane() : ScrollTextAreaPane = textpane;
  def getTextArea() : EditorPane = textpane.textarea;
  def getFileName() : String = maindatei.toString
  
  def hasFile() : Boolean = saved;
  def isActualSaved() : Boolean = !edited;
  def isParsed() : Boolean = parsed;
  
  def setName(n: String) : Unit = {
    this.name = n
  }
  
  /*
   * schreibt toString in t1 sowie protocol in t2
   * (vom geparsten TextArea des TextPanes)
   */
  def showProject(t1: EditorPane, t2: EditorPane, t3: EditorPane, t4: EditorPane) : Unit = {
    t1.text = this.t1
    t2.text = this.t2
    t3.text = this.t3
    t4.text = this.t4
  }
  
  /*
   * Gibt den Index des zum Projekt assozierten Tabs zurueck
   */
  def getTabIndex() : Int = {
    var ret = -1
    for(i <- 0 to tabpane.peer.getTabCount-1) {
      if(tabpane.peer.getComponentAt(i).equals(textpane.peer))
        ret = i
    }
    return ret
  }
  
  /*
   * Speichert den Inhalt aus dem Textarea des zum Objekt
   * verlinkten ScrollTextAreaPane in einer Datei.
   * Falls das Projekt noch keine Datei hat, wird 
   * saveToNewFile aufgerufen.
   */
  def saveToFile(tt:Layout) = {
    //Pruefen ob Datei bereits existiert
    if(saved == false || maindatei == null) {
      saveToNewFile(tt)
    }
    else {
      var writer:FileWriter = null
      try {
        writer = new FileWriter(maindatei)
        val LINESEPARATOR = System.getProperty("line.separator")
        var zeilen = textpane.textarea.text.split("\n")
        for(i <- 0 to (zeilen.length-1)) {
          writer.append(zeilen(i))
          if(i < (zeilen.length-1))
            writer.append("\n") //(LINESEPARATOR)
        }
      } 
      catch { 
        case e: IOException =>  //geht nicht, LOG-FILE?!
      } 
      finally {  
        if(writer != null) {
          edited = false
          tabpane.peer.setTitleAt(getTabIndex(), name)

          try {writer.close();} 
          catch { case e:IOException => }//geht nicht, LOG-FILE?!
        }  
      }
    }
  }
  
   /*
   * Speichert den Inhalt aus dem Textarea des zum Objekt
   * verlinkten ScrollTextAreaPane in einer neuen/anderen
   * Datei.
   */
  
  def saveToNewFile(tt:Layout) = {
    val chooser = new FileChooser {
      multiSelectionEnabled = false
      fileFilter = new FileNameExtensionFilter("Textdateien","txt")
    }
    var path = LOC.filePath
    if(maindatei != null)
      path = maindatei.getParent
    chooser.peer.setCurrentDirectory(new File(path))
    chooser.showSaveDialog(tt)
    if(chooser.selectedFile != null) {
      var r:Result.Value = null
      var abspath = chooser.selectedFile.getAbsolutePath
      //Dateiendung
      var ext = chooser.peer.getFileFilter() match {
        case x:FileNameExtensionFilter => x
        case _ => null
      }
      var typ = ""
      if(ext != null)
        typ = "." + ext.getExtensions()(0)

      //Falls Datei schon existiert
      if(chooser.selectedFile.exists ||
         (new File(chooser.selectedFile.getAbsoluteFile + "" + typ).exists)) {
        if(!chooser.selectedFile.exists)
          typ = "." + ext.getExtensions()(0)
        else
          typ = ""
        r = Dialog.showConfirmation(tt, LOC.get("DateiExistiert"),
                                    LOC.get("DateiExistiertTitel"),
                                    Dialog.Options.YesNo, Dialog.Message.Question)
      }
      //Pruefen ob Datei existiert, oder ob ueberschrieben werden soll
      if(!chooser.selectedFile.exists || (chooser.selectedFile.exists && r.equals(Result.Yes)))
      {
        abspath = abspath + "" + typ
        var writer:FileWriter = null
        try {
          writer = new FileWriter(abspath)
          val LINESEPARATOR = System.getProperty("line.separator")
          var zeilen = tt.getSelectedTabTopText.split("\n")
          for(i <- 0 to (zeilen.length-1)) {
            writer.append(zeilen(i))
            if(i < (zeilen.length-1))
              writer.append(LINESEPARATOR)
          }
          
          //Pfad merken
          var prop = new Properties()
          var fis = new FileInputStream(CONST.CONFIG_FILE)
          prop.load(fis)
          prop.setProperty("filePath", chooser.selectedFile.getParentFile.getName)
          LOC.filePath = chooser.selectedFile.getParentFile.getName
          var fos = new FileOutputStream(CONST.CONFIG_FILE)
          prop.store(fos, "config")
          fos.close()
        } 
        catch { 
          case e: IOException => Dialog.showMessage(tt, LOC.get("FehlerSpeichern"),
                                                    LOC.get("Fehler"), Dialog.Message.Error)
        } 
        finally {  
          if(writer != null) {
            saved = true
            edited = false
            name = chooser.selectedFile.getName + "" + typ
            maindatei = new File(abspath)
            tt.tabstop.peer.setTitleAt(tt.tabstop.getSelectedIndex, name)

            try {writer.close();} 
            catch { case e:IOException => Dialog.showMessage(tt, e.printStackTrace(),
                                                             LOC.get("Fehler"),
                                                             Dialog.Message.Error) }
          }  
        }
      }            
    }
  }
  
  
  def saveOutpuToFile(tt: Layout, j: Int, h: String) = {
    var tmpH = h.replace(".adb", "").split("_")
    
    var filename = maindatei.getParent + "\\"
    j match {
      case 1 => filename += "Out";
      case 2 => filename += "Trace";
      case 3 => filename += "Prop";
      case 4 => filename += "Proof";
    }
    for(i <- 1 to tmpH.length-1)
      filename += "_" + tmpH(i)
    if(j == 3)
      filename += ".adb"
    else
      filename += ".txt"
    
    j match {
      case 1 => t1file = new File(filename).getName
      case 2 => t2file = new File(filename).getName
      case 3 => t3file = new File(filename).getName
      case 4 => t4file = new File(filename).getName
    }

    var r: Result.Value = null
    if(new File(filename).exists) {
      r = Dialog.showConfirmation(tt, LOC.get("DateiExistiert"),
                                  LOC.get("DateiExistiertTitel"), Dialog.Options.YesNo,
                                  Dialog.Message.Question)
    }
    
    if(r == null || r.equals(Result.Yes)) {
      var writer:FileWriter = null
      try {
        writer = new FileWriter(filename)
        var zeilen = getT(j).split("\n")
        for(i <- 0 to (zeilen.length-1)) {
          writer.append(zeilen(i))
          if(i < (zeilen.length-1))
            writer.append("\n")
        }
      } 
      catch { 
        case e: IOException =>  //geht nicht, LOG-FILE?!
      } 
      finally {  
        if(writer != null) {
          try {writer.close();} 
          catch { case e:IOException => }//geht nicht, LOG-FILE?!
        }  
      }
    }
  }
  
  def loadOutput(): Unit = {
    t1 = ""
    t2 = ""
    t3 = ""
    t4 = ""
    t1file = ""
    t2file = ""
    t3file = ""
    t4file = ""
    if(maindatei != null) {
      var dir = maindatei.getParentFile()
      var pname = name.replace(".adb","")
      var tnr:String = null
      if(testfile != null) {
        var tnrA = testfile.getName.replace(".adb","").split("_")
        tnr = tnrA(tnrA.length-1)
      }
      for(i <- dir.listFiles) {
        var tname = i.getName()
        var tmpH = tname.split("_")
        if(tmpH.length >= 3) {
          var art = tmpH(0)
          var tpack = tmpH(1)
          var tproc = tmpH(2).toLowerCase.replace(".adb","").replace(".txt","")
          var nr = tmpH(tmpH.length-1).toLowerCase.replace(".txt","")

          if(pname.toLowerCase.equals(tpack.toLowerCase) && testproc != null) {
            if(art.equals("Out") && testproc.toLowerCase.equals(tproc.toLowerCase)) {
              t1 = scala.io.Source.fromFile(i).mkString
              t1file = i.getName
            }  
            else if(art.equals("Trace") && testproc.toLowerCase.equals(tproc.toLowerCase) && 
                    nr.equals(tnr)) {
              t2 = scala.io.Source.fromFile(i).mkString
              t2file = i.getName
            }  
            else if(art.equals("Prop") && testproc.toLowerCase.equals(tproc.toLowerCase) && 
                    nr.toLowerCase.endsWith(".adb")) {
              t3 = scala.io.Source.fromFile(i).mkString
              t3file = i.getName
            }  
            else if(art.equals("Proof") && testproc.toLowerCase.equals(tproc.toLowerCase)) {
              t4 = scala.io.Source.fromFile(i).mkString
              t4file = i.getName
            }
          }
        } 
      }
    }
  }
  
  
  def getT(i: Int): String = {
    i match {
      case 1 => return t1
      case 2 => return t2
      case 3 => return t3
      case 4 => return t4
    }
  }
  
  def setT(i: Int, a: String) = {
    i match {
      case 1 => t1 = a
      case 2 => t2 = a
      case 3 => t3 = a
      case 4 => t4 = a
    }
  }
  
}


 